home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / WindowMaker / WINGs / wfontpanel.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-03-28  |  22.5 KB  |  997 lines

  1.  
  2.  
  3.  
  4.  
  5. #include "WINGsP.h"
  6. #include "WUtil.h"
  7.  
  8. #include <ctype.h>
  9. #include <strings.h>
  10.  
  11.  
  12. typedef struct W_FontPanel {
  13.     WMWindow *win;
  14.  
  15.     WMFrame *upperF;
  16.     WMTextField *sampleT;
  17.     
  18.     WMSplitView *split;
  19.  
  20.     WMFrame *lowerF;
  21.     WMLabel *famL;
  22.     WMList *famLs;
  23.     WMLabel *typL;
  24.     WMList *typLs;
  25.     WMLabel *sizL;
  26.     WMTextField *sizT;
  27.     WMList *sizLs;
  28.  
  29.     WMButton *revertB;
  30.     WMButton *setB;
  31.     
  32.     proplist_t fdb;
  33. } FontPanel;
  34.  
  35.  
  36. #define MIN_UPPER_HEIGHT    20
  37. #define MIN_LOWER_HEIGHT    140
  38.  
  39.  
  40. #define MAX_FONTS_TO_RETRIEVE    2000
  41.  
  42. #define BUTTON_SPACE_HEIGHT 40
  43.  
  44. #define MIN_WIDTH    250
  45. #define MIN_HEIGHT     (MIN_UPPER_HEIGHT+MIN_LOWER_HEIGHT+BUTTON_SPACE_HEIGHT)
  46.  
  47. #define DEF_UPPER_HEIGHT 60
  48. #define DEF_LOWER_HEIGHT 310
  49.  
  50. #define DEF_WIDTH    320
  51. #define DEF_HEIGHT    (DEF_UPPER_HEIGHT+DEF_LOWER_HEIGHT)
  52.  
  53.  
  54.  
  55.  
  56. static int scalableFontSizes[] = {
  57.     8, 
  58.     10,
  59.     11,
  60.     12,
  61.     14,
  62.     16,
  63.     18,
  64.     20,
  65.     24,
  66.     36,
  67.     48,
  68.     64
  69. };
  70.  
  71.     
  72.  
  73. static void getSelectedFont(FontPanel *panel, char buffer[]);
  74.  
  75.  
  76. static void arrangeLowerFrame(FontPanel *panel);
  77.  
  78. static void familyClick(WMWidget *, void *);
  79. static void typefaceClick(WMWidget *, void *);
  80. static void sizeClick(WMWidget *, void *);
  81.  
  82.  
  83. static void listFamilies(WMScreen *scr, WMFontPanel *panel);
  84.  
  85.  
  86. static void
  87. splitViewConstrainCallback(WMSplitView *sPtr, int indView, int *min, int *max)
  88. {
  89.     if (indView == 0)    
  90.         *min = MIN_UPPER_HEIGHT;
  91.     else
  92.         *min = MIN_LOWER_HEIGHT;
  93. }
  94.  
  95. static void
  96. notificationObserver(void *self, WMNotification *notif)
  97. {
  98.     WMFontPanel *panel = (WMFontPanel*)self;
  99.     void *object = WMGetNotificationObject(notif);
  100.  
  101.     if (WMGetNotificationName(notif) == WMViewSizeDidChangeNotification) {
  102.     if (object == WMWidgetView(panel->win)) {
  103.         int h = WMWidgetHeight(panel->win);
  104.         int w = WMWidgetWidth(panel->win);
  105.  
  106.         WMResizeWidget(panel->split, w, h-BUTTON_SPACE_HEIGHT);
  107.  
  108.         WMMoveWidget(panel->setB, w-80, h-(BUTTON_SPACE_HEIGHT-5));
  109.  
  110.         WMMoveWidget(panel->revertB, w-240, h-(BUTTON_SPACE_HEIGHT-5));
  111.  
  112.     } else if (object == WMWidgetView(panel->upperF)) {
  113.  
  114.         if (WMWidgetHeight(panel->upperF) < MIN_UPPER_HEIGHT) {
  115.         WMResizeWidget(panel->upperF, WMWidgetWidth(panel->upperF),
  116.                    MIN_UPPER_HEIGHT);
  117.         } else {
  118.         WMResizeWidget(panel->sampleT, WMWidgetWidth(panel->upperF)-20,
  119.                    WMWidgetHeight(panel->upperF)-10);
  120.         }
  121.  
  122.     } else if (object == WMWidgetView(panel->lowerF)) {
  123.         
  124.         if (WMWidgetHeight(panel->lowerF) < MIN_LOWER_HEIGHT) {
  125.         WMResizeWidget(panel->upperF, WMWidgetWidth(panel->upperF), 
  126.                    MIN_UPPER_HEIGHT);
  127.  
  128.         WMMoveWidget(panel->lowerF, 0, WMWidgetHeight(panel->upperF)
  129.                  + WMGetSplitViewDividerThickness(panel->split));
  130.  
  131.         WMResizeWidget(panel->lowerF, WMWidgetWidth(panel->lowerF),
  132.                    WMWidgetWidth(panel->split) - MIN_UPPER_HEIGHT
  133.                    - WMGetSplitViewDividerThickness(panel->split));
  134.         } else {
  135.         arrangeLowerFrame(panel);
  136.         }
  137.     }
  138.     }
  139. }
  140.  
  141.  
  142. static void
  143. closeWindow(WMWidget *w, void *data)
  144. {
  145.     FontPanel *panel = (FontPanel*)data;
  146.     
  147.     WMHideFontPanel(panel);
  148. }
  149.  
  150.  
  151.  
  152. WMFontPanel*
  153. WMGetFontPanel(WMScreen *scr)
  154. {
  155.     FontPanel *panel;
  156.     WMColor *dark, *white;
  157.     WMFont *font;
  158.     int divThickness;
  159.  
  160.     if (scr->sharedFontPanel)
  161.     return scr->sharedFontPanel;
  162.  
  163.  
  164.     panel = wmalloc(sizeof(FontPanel));
  165.     memset(panel, 0, sizeof(FontPanel));
  166.     
  167.     panel->win = WMCreateWindow(scr, "fontPanel");
  168. /*    WMSetWidgetBackgroundColor(panel->win, WMWhiteColor(scr));*/
  169.     WMResizeWidget(panel->win, DEF_WIDTH, DEF_HEIGHT);
  170.     WMSetWindowMinSize(panel->win, MIN_WIDTH, MIN_HEIGHT);
  171.     WMSetViewNotifySizeChanges(WMWidgetView(panel->win), True);
  172.     
  173.     WMSetWindowCloseAction(panel->win, closeWindow, panel);
  174.  
  175.     panel->split = WMCreateSplitView(panel->win);
  176.     WMResizeWidget(panel->split, DEF_WIDTH, DEF_HEIGHT - BUTTON_SPACE_HEIGHT);
  177.     WMSetSplitViewConstrainProc(panel->split, splitViewConstrainCallback);
  178.  
  179.     divThickness = WMGetSplitViewDividerThickness(panel->split);
  180.  
  181.     panel->upperF = WMCreateFrame(panel->win);
  182.     WMSetFrameRelief(panel->upperF, WRFlat);
  183.     WMSetViewNotifySizeChanges(WMWidgetView(panel->upperF), True);
  184.     panel->lowerF = WMCreateFrame(panel->win);
  185. /*    WMSetWidgetBackgroundColor(panel->lowerF, WMBlackColor(scr));*/
  186.     WMSetFrameRelief(panel->lowerF, WRFlat);
  187.     WMSetViewNotifySizeChanges(WMWidgetView(panel->lowerF), True);
  188.  
  189.     WMAddSplitViewSubview(panel->split, W_VIEW(panel->upperF));
  190.     WMAddSplitViewSubview(panel->split, W_VIEW(panel->lowerF));
  191.  
  192.     WMResizeWidget(panel->upperF, DEF_WIDTH, DEF_UPPER_HEIGHT);
  193.     
  194.     WMResizeWidget(panel->lowerF, DEF_WIDTH, DEF_LOWER_HEIGHT);
  195.  
  196.     WMMoveWidget(panel->lowerF, 0, 60+divThickness);
  197.  
  198.     white = WMWhiteColor(scr);
  199.     dark = WMDarkGrayColor(scr);
  200.  
  201.     panel->sampleT = WMCreateTextField(panel->upperF);
  202.     WMResizeWidget(panel->sampleT, DEF_WIDTH - 20, 50);
  203.     WMMoveWidget(panel->sampleT, 10, 10);
  204.     WMSetTextFieldText(panel->sampleT, "Test!!!");
  205.  
  206.     font = WMBoldSystemFontOfSize(scr, 12);
  207.  
  208.     panel->famL = WMCreateLabel(panel->lowerF);
  209.     WMSetWidgetBackgroundColor(panel->famL, dark);
  210.     WMSetLabelText(panel->famL, "Family");
  211.     WMSetLabelFont(panel->famL, font);
  212.     WMSetLabelTextColor(panel->famL, white);
  213.     WMSetLabelRelief(panel->famL, WRSunken);
  214.     WMSetLabelTextAlignment(panel->famL, WACenter);
  215.     
  216.     panel->famLs = WMCreateList(panel->lowerF);
  217.     WMSetListAction(panel->famLs, familyClick, panel);
  218.  
  219.     panel->typL = WMCreateLabel(panel->lowerF);
  220.     WMSetWidgetBackgroundColor(panel->typL, dark);
  221.     WMSetLabelText(panel->typL, "Typeface");
  222.     WMSetLabelFont(panel->typL, font);
  223.     WMSetLabelTextColor(panel->typL, white);
  224.     WMSetLabelRelief(panel->typL, WRSunken);
  225.     WMSetLabelTextAlignment(panel->typL, WACenter);    
  226.  
  227.     panel->typLs = WMCreateList(panel->lowerF);
  228.     WMSetListAction(panel->typLs, typefaceClick, panel);
  229.  
  230.     panel->sizL = WMCreateLabel(panel->lowerF);
  231.     WMSetWidgetBackgroundColor(panel->sizL, dark);
  232.     WMSetLabelText(panel->sizL, "Size");
  233.     WMSetLabelFont(panel->sizL, font);
  234.     WMSetLabelTextColor(panel->sizL, white);
  235.     WMSetLabelRelief(panel->sizL, WRSunken);
  236.     WMSetLabelTextAlignment(panel->sizL, WACenter);
  237.  
  238.     panel->sizT = WMCreateTextField(panel->lowerF);
  239. /*    WMSetTextFieldAlignment(panel->sizT, WARight);*/
  240.  
  241.     panel->sizLs = WMCreateList(panel->lowerF);
  242.     WMSetListAction(panel->sizLs, sizeClick, panel);
  243.  
  244.     WMReleaseFont(font);
  245.     WMReleaseColor(white);
  246.     WMReleaseColor(dark);
  247.     
  248.     panel->setB = WMCreateCommandButton(panel->win);
  249.     WMResizeWidget(panel->setB, 70, 24);
  250.     WMMoveWidget(panel->setB, 240, DEF_HEIGHT - (BUTTON_SPACE_HEIGHT-5));
  251.     WMSetButtonText(panel->setB, "Set");
  252.  
  253.     panel->revertB = WMCreateCommandButton(panel->win);
  254.     WMResizeWidget(panel->revertB, 70, 24);
  255.     WMMoveWidget(panel->revertB, 80, DEF_HEIGHT - (BUTTON_SPACE_HEIGHT-5));
  256.     WMSetButtonText(panel->revertB, "Revert");
  257.  
  258.     WMRealizeWidget(panel->win);
  259.  
  260.     WMMapSubwidgets(panel->upperF);
  261.     WMMapSubwidgets(panel->lowerF);
  262.     WMMapSubwidgets(panel->split);
  263.     WMMapSubwidgets(panel->win);
  264.  
  265.     WMUnmapWidget(panel->revertB);
  266.  
  267.     arrangeLowerFrame(panel);
  268.  
  269.     scr->sharedFontPanel = panel;
  270.  
  271.  
  272.     /* register notification observers */
  273.     WMAddNotificationObserver(notificationObserver, panel, 
  274.                   WMViewSizeDidChangeNotification,
  275.                   WMWidgetView(panel->win));
  276.     WMAddNotificationObserver(notificationObserver, panel, 
  277.                   WMViewSizeDidChangeNotification, 
  278.                   WMWidgetView(panel->upperF));
  279.     WMAddNotificationObserver(notificationObserver, panel, 
  280.                   WMViewSizeDidChangeNotification, 
  281.                   WMWidgetView(panel->lowerF));
  282.  
  283.  
  284.     listFamilies(scr, panel);
  285.  
  286.     
  287.     return panel;
  288. }
  289.  
  290.  
  291. void
  292. WMFreeFontPanel(WMFontPanel *panel)
  293. {
  294.     if (panel == WMWidgetScreen(panel->win)->sharedFontPanel) {
  295.     WMWidgetScreen(panel->win)->sharedFontPanel = NULL;
  296.     }
  297.     WMRemoveNotificationObserver(panel);
  298.     WMUnmapWidget(panel->win);
  299.     WMDestroyWidget(panel->win);
  300.     wfree(panel);
  301. }
  302.  
  303.  
  304. void
  305. WMShowFontPanel(WMFontPanel *panel)
  306. {
  307.     WMMapWidget(panel->win);
  308. }
  309.  
  310.  
  311. void
  312. WMHideFontPanel(WMFontPanel *panel)
  313. {
  314.     WMUnmapWidget(panel->win);
  315. }
  316.  
  317.  
  318. void
  319. WMSetFontPanelFont(WMFontPanel *panel, WMFont *font)
  320. {
  321.     
  322. }
  323.  
  324.  
  325. Bool
  326. WMSetFontPanelFontName(WMFontPanel *panel, char *fontName)
  327. {
  328.  
  329.     return True;
  330. }
  331.  
  332.  
  333. WMFont*
  334. WMGetFontPanelFont(WMFontPanel *panel)
  335. {
  336.     return WMGetTextFieldFont(panel->sampleT);
  337. }
  338.  
  339.  
  340. char*
  341. WMGetFontPanelFontName(WMFontPanel *panel)
  342. {
  343.     char name[256];
  344.  
  345.     getSelectedFont(panel, name);
  346.  
  347.     return wstrdup(name);
  348. }
  349.  
  350.  
  351.  
  352. static void
  353. arrangeLowerFrame(FontPanel *panel)
  354. {
  355.     int width = WMWidgetWidth(panel->lowerF) - 55 - 30;
  356.     int height = WMWidgetHeight(panel->split) - WMWidgetHeight(panel->upperF);
  357.     int fw, tw, sw;
  358.  
  359. #define LABEL_HEIGHT 20
  360.  
  361.     height -= WMGetSplitViewDividerThickness(panel->split);
  362.     
  363.  
  364.     height -= LABEL_HEIGHT + 8;
  365.  
  366.     fw = (125*width) / 235;
  367.     tw = (110*width) / 235;
  368.     sw = 55;
  369.  
  370.     WMMoveWidget(panel->famL, 10, 0);
  371.     WMResizeWidget(panel->famL, fw, LABEL_HEIGHT);
  372.  
  373.     WMMoveWidget(panel->famLs, 10, 23);
  374.     WMResizeWidget(panel->famLs, fw, height);
  375.  
  376.     WMMoveWidget(panel->typL, 10+fw+3, 0);
  377.     WMResizeWidget(panel->typL, tw, LABEL_HEIGHT);
  378.  
  379.     WMMoveWidget(panel->typLs, 10+fw+3, 23);
  380.     WMResizeWidget(panel->typLs, tw, height);
  381.  
  382.     WMMoveWidget(panel->sizL, 10+fw+3+tw+3, 0);
  383.     WMResizeWidget(panel->sizL, sw+4, LABEL_HEIGHT);
  384.  
  385.     WMMoveWidget(panel->sizT, 10+fw+3+tw+3, 23);
  386.     WMResizeWidget(panel->sizT, sw+4, 20);
  387.  
  388.     WMMoveWidget(panel->sizLs, 10+fw+3+tw+3, 46);
  389.     WMResizeWidget(panel->sizLs, sw+4, height-23);
  390. }
  391.  
  392.  
  393.  
  394.  
  395. #define ALL_FONTS_MASK  "-*-*-*-*-*-*-*-*-*-*-*-*-*-*"
  396.  
  397. #define FOUNDRY    0
  398. #define FAMILY    1
  399. #define WEIGHT    2
  400. #define SLANT    3
  401. #define SETWIDTH 4
  402. #define ADD_STYLE 5
  403. #define PIXEL_SIZE 6
  404. #define POINT_SIZE 7
  405. #define RES_X    8
  406. #define RES_Y    9
  407. #define SPACING    10
  408. #define AV_WIDTH 11
  409. #define REGISTRY 12
  410. #define ENCODING 13
  411.  
  412. #define NUM_FIELDS 14
  413.  
  414.  
  415.  
  416. static Bool
  417. parseFont(char *font, char values[NUM_FIELDS][256])
  418. {
  419.     char *ptr;
  420.     int part;
  421.     char buffer[256], *bptr;
  422.  
  423.     part = FOUNDRY;
  424.     ptr = font;
  425.     ptr++; /* skip first - */
  426.     bptr = buffer;
  427.     while (*ptr) {
  428.     if (*ptr == '-') {
  429.         *bptr = 0;
  430.         strcpy(values[part], buffer);
  431.         bptr = buffer;
  432.         part++;
  433.     } else {
  434.         *bptr++ = *ptr;
  435.     }
  436.     ptr++;
  437.     }
  438.     *bptr = 0;
  439.     strcpy(values[part], buffer);
  440.     
  441.     return True;
  442. }
  443.  
  444.  
  445.  
  446. static int
  447. isXLFD(char *font, int *length_ret)
  448. {
  449.     int c = 0;
  450.     
  451.     *length_ret = 0;
  452.     while (*font) {
  453.     (*length_ret)++;
  454.     if (*font++ == '-')
  455.         c++;
  456.     }
  457.  
  458.     return c==NUM_FIELDS;
  459. }
  460.  
  461.  
  462.  
  463.  
  464. typedef struct {
  465.     char *weight;
  466.     char *slant;
  467.  
  468.     char *setWidth;
  469.     char *addStyle;
  470.     
  471.     char showSetWidth; /* when duplicated */
  472.     char showAddStyle; /* when duplicated */
  473.     
  474.     WMBag *sizes;
  475. } Typeface;
  476.  
  477.  
  478. typedef struct {
  479.     char *name;
  480.  
  481.     char *foundry;
  482.     char *registry, *encoding;
  483.  
  484.     char showFoundry; /* when duplicated */
  485.     char showRegistry; /* when duplicated */
  486.  
  487.     WMBag *typefaces;
  488. } Family;
  489.  
  490.  
  491.  
  492.  
  493. static int
  494. compare_int(const void *a, const void *b)
  495. {
  496.     int i1 = *(int*)a;
  497.     int i2 = *(int*)b;
  498.  
  499.     if (i1 < i2)
  500.     return -1;
  501.     else if (i1 > i2)
  502.     return 1;
  503.     else
  504.     return 0;
  505. }
  506.  
  507.  
  508.  
  509. static void
  510. addSizeToTypeface(Typeface *face, int size)
  511. {
  512.     if (size == 0) {
  513.     int j;
  514.         
  515.     for (j = 0; j < sizeof(scalableFontSizes)/sizeof(int); j++) {
  516.         size = scalableFontSizes[j];
  517.  
  518.         if (!WMCountInBag(face->sizes, (void*)size)) {
  519.         WMPutInBag(face->sizes, (void*)size);
  520.         }
  521.     }
  522.     WMSortBag(face->sizes, compare_int);
  523.     } else {
  524.     if (!WMCountInBag(face->sizes, (void*)size)) {
  525.         WMPutInBag(face->sizes, (void*)size);
  526.         WMSortBag(face->sizes, compare_int);
  527.     }
  528.     }
  529. }
  530.  
  531.  
  532.  
  533. static void
  534. addTypefaceToFamily(Family *family, char fontFields[NUM_FIELDS][256])
  535. {
  536.     Typeface *face;
  537.     WMBagIterator i;
  538.  
  539.     if (family->typefaces) {
  540.     for (face = WMBagFirst(family->typefaces, &i);
  541.          face != NULL;
  542.          face = WMBagNext(family->typefaces, &i)) {
  543.         int size;
  544.  
  545.         if (strcmp(face->weight, fontFields[WEIGHT]) != 0) {
  546.         continue;
  547.         }
  548.         if (strcmp(face->slant, fontFields[SLANT]) != 0) {
  549.         continue;
  550.         }
  551.  
  552.         size = atoi(fontFields[PIXEL_SIZE]);
  553.  
  554.         addSizeToTypeface(face, size);
  555.  
  556.         return;
  557.     }
  558.     } else {
  559.     family->typefaces = WMCreateBag(4);
  560.     }
  561.  
  562.     face = wmalloc(sizeof(Typeface));
  563.     memset(face, 0, sizeof(Typeface));
  564.  
  565.     face->weight = wstrdup(fontFields[WEIGHT]);
  566.     face->slant = wstrdup(fontFields[SLANT]);
  567.     face->setWidth = wstrdup(fontFields[SETWIDTH]);
  568.     face->addStyle = wstrdup(fontFields[ADD_STYLE]);
  569.  
  570.     face->sizes = WMCreateBag(4);
  571.     addSizeToTypeface(face, atoi(fontFields[PIXEL_SIZE]));
  572.  
  573.     WMPutInBag(family->typefaces, face);
  574. }
  575.  
  576.  
  577.  
  578. /*
  579.  * families (same family name) (Hashtable of family -> bag)
  580.  *     registries (same family but different registries)
  581.  * 
  582.  */
  583.  
  584. static void
  585. addFontToFamily(WMHashTable *families, char fontFields[NUM_FIELDS][256])
  586. {
  587.     WMBagIterator i;
  588.     Family *fam;
  589.     WMBag *family;
  590.  
  591.  
  592.     family = WMHashGet(families, fontFields[FAMILY]);
  593.     
  594.     if (family) {
  595.     /* look for same encoding/registry and foundry */
  596.     for (fam = WMBagFirst(family, &i);
  597.          fam != NULL;
  598.          fam = WMBagNext(family, &i)) {
  599.         int enc, reg, found;
  600.  
  601.         enc = (strcmp(fam->encoding, fontFields[ENCODING]) == 0);
  602.         reg = (strcmp(fam->registry, fontFields[REGISTRY]) == 0);
  603.         found = (strcmp(fam->foundry, fontFields[FOUNDRY]) == 0);
  604.  
  605.         if (enc && reg && found) {
  606.         addTypefaceToFamily(fam, fontFields);
  607.         return;
  608.         }
  609.     }
  610.     /* look for same encoding/registry */
  611.     for (fam = WMBagFirst(family, &i);
  612.          fam != NULL;
  613.          fam = WMBagNext(family, &i)) {
  614.         int enc, reg;
  615.         
  616.         enc = (strcmp(fam->encoding, fontFields[ENCODING]) == 0);
  617.         reg = (strcmp(fam->registry, fontFields[REGISTRY]) == 0);
  618.  
  619.         if (enc && reg) {
  620.         /* has the same encoding, but the foundry is different */
  621.         fam->showFoundry = 1;
  622.  
  623.         fam = wmalloc(sizeof(Family));
  624.         memset(fam, 0, sizeof(Family));
  625.  
  626.         fam->name = wstrdup(fontFields[FAMILY]);
  627.         fam->foundry = wstrdup(fontFields[FOUNDRY]);
  628.         fam->registry = wstrdup(fontFields[REGISTRY]);
  629.         fam->encoding = wstrdup(fontFields[ENCODING]);
  630.         fam->showFoundry = 1;
  631.  
  632.         addTypefaceToFamily(fam, fontFields);
  633.  
  634.         WMPutInBag(family, fam);
  635.         return;
  636.         }
  637.     }
  638.     /* look for same foundry */
  639.     for (fam = WMBagFirst(family, &i);
  640.          fam != NULL;
  641.          fam = WMBagNext(family, &i)) {
  642.         int found;
  643.         
  644.         found = (strcmp(fam->foundry, fontFields[FOUNDRY]) == 0);
  645.  
  646.         if (found) {
  647.         /* has the same foundry, but encoding is different */
  648.         fam->showRegistry = 1;
  649.  
  650.         fam = wmalloc(sizeof(Family));
  651.         memset(fam, 0, sizeof(Family));
  652.  
  653.         fam->name = wstrdup(fontFields[FAMILY]);
  654.         fam->foundry = wstrdup(fontFields[FOUNDRY]);
  655.         fam->registry = wstrdup(fontFields[REGISTRY]);
  656.         fam->encoding = wstrdup(fontFields[ENCODING]);
  657.         fam->showRegistry = 1;
  658.  
  659.         addTypefaceToFamily(fam, fontFields);
  660.  
  661.         WMPutInBag(family, fam);
  662.         return;
  663.         }
  664.     }
  665.     /* foundry and encoding do not match anything known */
  666.     fam = wmalloc(sizeof(Family));
  667.     memset(fam, 0, sizeof(Family));
  668.  
  669.     fam->name = wstrdup(fontFields[FAMILY]);
  670.     fam->foundry = wstrdup(fontFields[FOUNDRY]);
  671.     fam->registry = wstrdup(fontFields[REGISTRY]);
  672.     fam->encoding = wstrdup(fontFields[ENCODING]);
  673.     fam->showFoundry = 1;
  674.     fam->showRegistry = 1;
  675.  
  676.     addTypefaceToFamily(fam, fontFields);
  677.  
  678.     WMPutInBag(family, fam);
  679.     return;
  680.     }
  681.  
  682.     family = WMCreateBag(8);
  683.  
  684.     fam = wmalloc(sizeof(Family));
  685.     memset(fam, 0, sizeof(Family));
  686.  
  687.     fam->name = wstrdup(fontFields[FAMILY]);
  688.     fam->foundry = wstrdup(fontFields[FOUNDRY]);
  689.     fam->registry = wstrdup(fontFields[REGISTRY]);
  690.     fam->encoding = wstrdup(fontFields[ENCODING]);
  691.     
  692.     addTypefaceToFamily(fam, fontFields);
  693.     
  694.     WMPutInBag(family, fam);
  695.  
  696.     WMHashInsert(families, fam->name, family);
  697. }
  698.  
  699.  
  700.  
  701. static void
  702. listFamilies(WMScreen *scr, WMFontPanel *panel)
  703. {
  704.     char **fontList;
  705.     int count;
  706.     int i;
  707.     WMHashTable *families = WMCreateHashTable(WMStringPointerHashCallbacks);
  708.     char fields[NUM_FIELDS][256];
  709.     WMHashEnumerator enumer;
  710.     WMBag *bag;
  711.     
  712.     fontList = XListFonts(scr->display, ALL_FONTS_MASK, MAX_FONTS_TO_RETRIEVE, 
  713.                           &count);
  714.     if (!fontList) {
  715.     WMRunAlertPanel(scr, panel->win, "Error", 
  716.             "Could not retrieve font list", "OK", NULL, NULL);
  717.     return;
  718.     }
  719.  
  720.     for (i = 0; i < count; i++) {
  721.     int fname_len;
  722.  
  723.     if (!isXLFD(fontList[i], &fname_len)) {
  724.         *fontList[i] = '\0';
  725.         continue;
  726.     }
  727.     if (fname_len > 255) {
  728.         wwarning("font name %s is longer than 256, which is invalid.",
  729.              fontList[i]);
  730.         *fontList[i] = '\0';
  731.         continue;
  732.     }
  733.     if (!parseFont(fontList[i], fields)) {
  734.         *fontList[i] = '\0';
  735.         continue;
  736.     }
  737.     addFontToFamily(families, fields);
  738.     }
  739.  
  740.     enumer = WMEnumerateHashTable(families);
  741.     
  742.     while ((bag = WMNextHashEnumeratorItem(&enumer))) {
  743.     WMBagIterator i;
  744.     Family *fam;
  745.     char buffer[256];
  746.     WMListItem *item;
  747.  
  748.     for (fam = WMBagFirst(bag, &i);
  749.          fam != NULL;
  750.          fam = WMBagNext(bag, &i)) {
  751.         
  752.         strcpy(buffer, fam->name);
  753.  
  754.         if (fam->showFoundry) {
  755.         strcat(buffer, " ");
  756.         strcat(buffer, fam->foundry);
  757.         strcat(buffer, " ");
  758.         }
  759.         if (fam->showRegistry) {
  760.         strcat(buffer, " (");
  761.         strcat(buffer, fam->registry);
  762.         strcat(buffer, "-");
  763.         strcat(buffer, fam->encoding);
  764.         strcat(buffer, ")");
  765.         }
  766.         item = WMAddListItem(panel->famLs, buffer);
  767.         
  768.         item->clientData = fam;
  769.     }
  770.     WMFreeBag(bag);
  771.     }
  772.     WMSortListItems(panel->famLs);
  773.     
  774.     WMFreeHashTable(families);
  775. }
  776.  
  777.  
  778. static void
  779. getSelectedFont(FontPanel *panel, char buffer[])
  780. {
  781.     WMListItem *item;
  782.     Family *family;
  783.     Typeface *face;
  784.     char *size;
  785.  
  786.     
  787.     item = WMGetListSelectedItem(panel->famLs);
  788.     if (!item)
  789.     return;
  790.     family = (Family*)item->clientData;
  791.  
  792.     item = WMGetListSelectedItem(panel->typLs);
  793.     if (!item)
  794.     return;
  795.     face = (Typeface*)item->clientData;
  796.  
  797.     size = WMGetTextFieldText(panel->sizT);
  798.  
  799.     sprintf(buffer, "-%s-%s-%s-%s-%s-%s-%s-*-*-*-*-*-%s-%s",
  800.         family->foundry,
  801.         family->name,
  802.         face->weight,
  803.         face->slant,
  804.         face->setWidth,
  805.         face->addStyle,
  806.         size,
  807.         family->registry,
  808.         family->encoding);
  809. }
  810.  
  811.  
  812.  
  813. static void
  814. preview(FontPanel *panel)
  815. {
  816.     char buffer[256];
  817.     WMFont *font;
  818.     
  819.     getSelectedFont(panel, buffer);
  820.     
  821.     font = WMCreateFont(WMWidgetScreen(panel->win), buffer);
  822.     if (font) {
  823.     WMSetTextFieldFont(panel->sampleT, font);
  824.     WMReleaseFont(font);
  825.     }
  826. }
  827.  
  828.  
  829.  
  830. static void 
  831. familyClick(WMWidget *w, void *data)
  832. {
  833.     WMList *lPtr = (WMList*)w;
  834.     WMListItem *item;
  835.     Family *family;
  836.     FontPanel *panel = (FontPanel*)data;
  837.     Typeface *face;
  838.     WMBagIterator i;
  839.     /* current typeface and size */
  840.     char *oface = NULL;
  841.     char *osize = NULL;
  842.     int facei = -1;
  843.     int sizei = -1;
  844.  
  845.     /* must try to keep the same typeface and size for the new family */
  846.     item = WMGetListSelectedItem(panel->typLs);
  847.     if (item)
  848.     oface = wstrdup(item->text);
  849.  
  850.     osize = WMGetTextFieldText(panel->sizT);
  851.  
  852.  
  853.     item = WMGetListSelectedItem(lPtr);
  854.     family = (Family*)item->clientData;
  855.  
  856.     WMClearList(panel->typLs);
  857.  
  858.  
  859.     for (face = WMBagFirst(family->typefaces, &i);
  860.      face != NULL;
  861.      face = WMBagNext(family->typefaces, &i)) {
  862.     char buffer[256];
  863.     int top=0;
  864.     WMListItem *fitem;
  865.     
  866.     if (strcmp(face->weight, "medium") == 0) {
  867.         buffer[0] = 0;
  868.     } else {
  869.         if (*face->weight) {
  870.         strcpy(buffer, face->weight);
  871.         buffer[0] = toupper(buffer[0]);
  872.         strcat(buffer, " ");
  873.         } else {
  874.         buffer[0] = 0;
  875.         }
  876.     }
  877.  
  878.     if (strcmp(face->slant, "r") == 0) {
  879.         strcat(buffer, "Roman");
  880.         top = 1;
  881.     } else if (strcmp(face->slant, "i") == 0) {
  882.         strcat(buffer, "Italic");
  883.     } else if (strcmp(face->slant, "o") == 0) {
  884.         strcat(buffer, "Oblique");
  885.     } else if (strcmp(face->slant, "ri") == 0) {
  886.         strcat(buffer, "Rev Italic");
  887.     } else if (strcmp(face->slant, "ro") == 0) {
  888.         strcat(buffer, "Rev Oblique");
  889.     } else {
  890.         strcat(buffer, face->slant);
  891.     }
  892.  
  893.     if (buffer[0] == 0) {
  894.         strcpy(buffer, "Normal");
  895.     }
  896.  
  897.     if (top)
  898.         fitem = WMInsertListItem(panel->typLs, 0, buffer);
  899.     else
  900.         fitem = WMAddListItem(panel->typLs, buffer);
  901.     fitem->clientData = face;
  902.     }
  903.  
  904.     if (oface) {
  905.     facei = WMFindRowOfListItemWithTitle(panel->typLs, oface);
  906.     wfree(oface);
  907.     }
  908.     if (facei < 0) {
  909.     facei = 0;
  910.     }
  911.     WMSelectListItem(panel->typLs, facei);
  912.     typefaceClick(panel->typLs, panel);
  913.     
  914.     if (osize) {
  915.     sizei = WMFindRowOfListItemWithTitle(panel->sizLs, osize);
  916.     }
  917.     if (sizei >= 0) {
  918.     WMSelectListItem(panel->sizLs, sizei);
  919.     sizeClick(panel->sizLs, panel);
  920.     }
  921.  
  922.     if (osize)
  923.     wfree(osize);
  924.  
  925.  
  926.     preview(panel);
  927. }
  928.  
  929.  
  930. static void 
  931. typefaceClick(WMWidget *w, void *data)
  932. {
  933.     FontPanel *panel = (FontPanel*)data;
  934.     WMListItem *item;
  935.     Typeface *face;
  936.     WMBagIterator i;
  937.     char buffer[32];
  938.  
  939.     char *osize = NULL;
  940.     int sizei = -1;
  941.     int size;
  942.  
  943.     osize = WMGetTextFieldText(panel->sizT);
  944.  
  945.  
  946.     item = WMGetListSelectedItem(panel->typLs);
  947.     face = (Typeface*)item->clientData;
  948.     
  949.     WMClearList(panel->sizLs);
  950.  
  951.     for (size = (int)WMBagFirst(face->sizes, &i);
  952.      i != NULL;
  953.      size = (int)WMBagNext(face->sizes, &i)) {
  954.  
  955.     if (size != 0) {
  956.         sprintf(buffer, "%i", size);
  957.  
  958.         WMAddListItem(panel->sizLs, buffer);
  959.     }
  960.     }
  961.  
  962.     if (osize) {
  963.     sizei = WMFindRowOfListItemWithTitle(panel->sizLs, osize);
  964.     }
  965.     if (sizei < 0) {
  966.     sizei = WMFindRowOfListItemWithTitle(panel->sizLs, "12");
  967.     }
  968.     if (sizei < 0) {
  969.     sizei = 0;
  970.     }
  971.     WMSelectListItem(panel->sizLs, sizei);
  972.     WMSetListPosition(panel->sizLs, sizei);
  973.     sizeClick(panel->sizLs, panel);
  974.  
  975.     if (osize)
  976.     wfree(osize);
  977.  
  978.     preview(panel);
  979. }
  980.  
  981.  
  982. static void 
  983. sizeClick(WMWidget *w, void *data)
  984. {
  985.     FontPanel *panel = (FontPanel*)data;
  986.     WMListItem *item;
  987.     
  988.     item = WMGetListSelectedItem(panel->sizLs);
  989.  
  990.     WMSetTextFieldText(panel->sizT, item->text);
  991.     
  992.     WMSelectTextFieldRange(panel->sizT, wmkrange(0, strlen(item->text)));
  993.  
  994.     preview(panel);
  995. }
  996.  
  997.